﻿using DbgHelp.MinidumpFiles.Native;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace DbgHelp.MinidumpFiles
{
    /// <summary>
    /// Contains exception information.
    /// </summary>
    public class MiniDumpException
    {
        private MINIDUMP_EXCEPTION _exception;
        private MiniDumpFile _owner;
        //private MiniDumpException _exceptionRecord;
        private UInt64[] _exceptionInformation;

        internal unsafe MiniDumpException(MINIDUMP_EXCEPTION exception, MiniDumpFile owner)
        {
            _exception = exception;
            _owner = owner;

            // Can't generate test data for this, so won't implement it yet. ExceptionRecord doesn't seem to be an RVA?
            //if (exception.ExceptionRecord != 0)
            //{
            //    MINIDUMP_EXCEPTION exceptionRecored = owner.ReadStructure<MINIDUMP_EXCEPTION>(exception.ExceptionRecord);
            //    _exceptionRecord = new MiniDumpException(exceptionRecored);
            //}

            _exceptionInformation = new UInt64[windows.EXCEPTION_MAXIMUM_PARAMETERS];

            for (int i = 0; i < windows.EXCEPTION_MAXIMUM_PARAMETERS; i++)
                _exceptionInformation[i] = exception.ExceptionInformation[i];
        }

        /// <summary>
        /// The reason the exception occurred. This is the code generated by a hardware exception, or the code specified in the RaiseException function for a software-generated exception.
        /// </summary>
        public UInt32 ExceptionCode { get { return this._exception.ExceptionCode; } }

        /// <summary>
        /// This member can be either zero, indicating a continuable exception, or <see cref="EXCEPTION_NONCONTINUABLE"/>, indicating a noncontinuable exception. Any attempt to continue execution after a noncontinuable exception causes the EXCEPTION_NONCONTINUABLE_EXCEPTION exception.
        /// </summary>
        public UInt32 ExceptionFlags { get { return this._exception.ExceptionFlags; } }

        /// <summary>
        /// A pointer to an associated MINIDUMP_EXCEPTION structure. Exception records can be chained together to provide additional information when nested exceptions occur.
        /// </summary>
        public UInt64 ExceptionRecordRaw { get { return this._exception.ExceptionRecord; } }

        /// <summary>
        /// The address where the exception occurred.
        /// </summary>
        public UInt64 ExceptionAddress { get { return this._exception.ExceptionAddress; } }

        /// <summary>
        /// The number of parameters associated with the exception. This is the number of defined elements in the ExceptionInformation array.
        /// </summary>
        public UInt32 NumberParameters { get { return this._exception.NumberParameters; } }

        /// <summary>
        /// An array of additional arguments that describe the exception. The RaiseException function can specify this array of arguments. For most exception codes, the array elements are undefined.
        /// </summary>
        public UInt64[] ExceptionInformation { get { return this._exceptionInformation; } }

        /// <summary>
        /// Noncontinuable exception.
        /// </summary>
        public static readonly UInt32 EXCEPTION_NONCONTINUABLE = 0x1;
    }
}
